package com.clp.util.hutool.core.net;

import com.clp.util.hutool.core.util.CharUtil;
import com.clp.util.hutool.core.util.StrUtil;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;

/**
 * URL解码，数据内容的类型是 application/x-www-form-urlencoded。
 *
 * <pre>
 * 1. 将%20转换为空格 ;
 * 2. 将"%xy"转换为文本形式,xy是两位16进制的数值;
 * 3. 跳过不符合规范的%形式，直接输出
 * </pre>
 *
 * @author looly
 */
public class URLDecoder {
    private static final byte ESCAPE_CHAR = '%';

    public static String decode(String str, Charset charset) {
        return StrUtil.str(decode(StrUtil.bytes(str, charset)), charset);
    }

    /**
     * 解码
     * @param bytes url编码的bytes
     * @return 解码后的bytes
     */
    public static byte[] decode(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        byte[] byteArray;
        try(final ByteArrayOutputStream buffer = new ByteArrayOutputStream(bytes.length)) {
            int b;
            for (int i = 0; i < bytes.length; i++) {
                b = bytes[i];
                if (b == '+') {
                    buffer.write(CharUtil.SPACE);
                } else if (b == ESCAPE_CHAR) {
                    if (i + 1 < bytes.length) {
                        final int u = CharUtil.digit16(bytes[i + 1]);
                        if (u >= 0 && i + 2 < bytes.length) {
                            final int l = CharUtil.digit16(bytes[i + 2]);
                            if (l >= 0) {
                                buffer.write((char) ((u << 4) + l));
                                i += 2;
                                continue;
                            }
                        }
                    }
                    // 跳过不符合规范的%形式
                    buffer.write(b);
                } else {
                    buffer.write(b);
                }
            }
            byteArray = buffer.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return byteArray;
    }
}
